package extend

import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

@OptIn(ExperimentalContracts::class)
inline fun <T, R> T.runIf(condition: Boolean, block: (T) -> R): R? {
    contract {
        callsInPlace(block, InvocationKind.AT_MOST_ONCE)
    }
    return if (condition)
        block(this)
    else null
}

@OptIn(ExperimentalContracts::class)
inline fun <T, R> T.runIf(condition: (T)-> Boolean, block: (T) -> R): R? {
    contract {
        callsInPlace(condition, InvocationKind.EXACTLY_ONCE)
    }
    return runIf(condition(this), block)
}

@OptIn(ExperimentalContracts::class)
inline fun <T> T.applyIf(condition: Boolean, block: (T) -> T): T {
    contract {
        callsInPlace(block, InvocationKind.AT_MOST_ONCE)
    }
    return if (condition) block(this) else this
}

@OptIn(ExperimentalContracts::class)
inline fun <T> T.applyIf(condition: (T)-> Boolean, block: (T) -> T): T {
    contract {
        callsInPlace(condition, InvocationKind.EXACTLY_ONCE)
    }
    return applyIf(condition(this), block)
}